#include <gtest/gtest.h>
#include "scripting/script_lexer.h"
#include "scripting/script_parser.h"
#include "test_print_info.h"

TEST(test_parser_scan_and_parser_var, test_parser)
{
    const char *code = R"(var get_pose_2 = get_pose("get_pose_2") #定义task)";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_parser_scan_and_parser_var_err, test_parser)
{
    const char *code = R"(var get_pose("get_pose*") #定义错误的task)";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        SUCCEED();
    }
}

TEST(test_parser_scan_and_parser_run, test_parser)
{
    const char *code = R"(get_pose#执行task)";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_parser_scan_scan_if_sample, test_parser)
{
    const char *code = R"(if(!check_battery){navigation})";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_parser_scan_scan_if_smple, test_parser)
{
    const char *code = R"(
        if(check_battery or get_pose)
        {
            navigation#运行导航
        }
        else
        {
            docking
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_parser_scan_scan_if_and_or, test_parser)
{
    const char *code = R"(
        if(!abd or check_battery and !get_pose or check_pose and get_battery)
        {
            navigation#运行导航
        }
        else
        {
            docking
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_parser_scan_scan_if_all_or, test_parser)
{
    const char *code = R"(
        if(abd or check_battery or !get_pose or check_pose or get_battery)
        {
            navigation#运行导航
        }
        else
        {
            docking
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_parser_scan_scan_if_all_and, test_parser)
{
    const char *code = R"(
        if(abd and check_battery and get_pose and check_pose and get_battery)
        {
            navigation#运行导航
        }
        else
        {
            docking
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_parser_scan_scan_if_nest, test_parser)
{
    const char *code = R"(
        if(check_battery or !(get_pose and check_pose))
        {
            navigation#运行导航
        }
        else
        {
            docking
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_parser_scan_scan_if_nest_2, test_parser)
{
    const char *code = R"(
        if(check_battery or (get_pose or check_pose))
        {
            navigation#运行导航
        }
        else
        {
            docking
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_script_parse_repeat, test_parser)
{
    const char *code = R"(
        #repeat
        repeat(3)
        {
            navigation
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_script_parse_retry, test_parser)
{
    const char *code = R"(
        #repeat
        retry(3)
        {
            navigation
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_script_parse_while_break, test_parser)
{
    const char *code = R"(
        #while
        while(arrived)
        {
            # sleep(1000)
            if(navigation)
            {
                break
            }
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_script_parse_while, test_parser)
{
    const char *code = R"(
        #while
        while(arrived)
        {
            navigation
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_script_parse_while_no_executant, test_parser)
{
    const char *code = R"(
        #while
        while(arrived)
        {
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_script_parse_reactive, test_parser)
{
    const char *code = R"(
        #reactive
        reactive(check_battery){
            navigation
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
TEST(test_script_parse_parallel, test_parser)
{
    const char *code = R"(
        #parallel
        parallel
        {
            navigation
            docking
            recharge
        }
    )";

    script::ScriptLexer script_lexer;
    auto tokens = script_lexer.scan(code);
    if (tokens)
    {
        printf("code: %s\n", code);
        script::ScriptParser script_parser;
        auto ast_node = script_parser.parse(tokens.value());
        if (ast_node)
        {
            printASTNode(ast_node.value());
            SUCCEED();
        }
        else
        {
            printASTError(script_parser);
            FAIL();
        }
    }
    else
    {
        FAIL();
    }
}
